﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using System.Windows.Forms;
using UCL;
using UCL.Forms;

namespace UCL.Forms.Components
{
    // 2013-7-20 by sutroon
    public partial class ucExplorer : UserControl
    {
        public Action<string> FolderChangeHandler { get; set; }
        public string FolderPath { get; set; }
        SoExplorer.ComDataHelper adh;
        public ucExplorer()
        {
            InitializeComponent();
        }

        private void ucExplorer_Load(object sender, EventArgs e)
        {
            lblSelectedTip.Text = string.Empty;
        }

        // 替代ucExplorer_Load，防止IDE界面展示的时候自动初始化数据
        public void InitLoad()
        {
            adh = new SoExplorer.ComDataHelper();
            ImageList imglist = new ImageList();
            imglist.Images.Add("file", UCL.Forms.Components.ComRes.file32);
            imglist.Images.Add("folder", UCL.Forms.Components.ComRes.folder32);
            imglist.ImageSize = new Size(32, 32);
            lvContents.LargeImageList = imglist;

            // 快捷菜单
            LoadLinks();
            // 磁盘驱动器
            LoadDrivers();

            MenuItemClickConfig();
        }

        // 默认桌面内容
        public void LoadLinks()
        {
            lbLinks.DataSource = adh.ExecuteDataTable("select * from tExplorerFavorite");
            lbLinks.DisplayMember = "Name";
            lbLinks.ValueMember = "HostUri";
        }
        // 默认桌面内容
        public void LoadDrivers()
        {
            tvDrivers.Nodes.Clear();
            string[] drivers = Directory.GetLogicalDrives();
            TreeNode tn; DriveInfo df;
            foreach (string d in drivers)
            {
                df = new DriveInfo(d);
                tn = new TreeNode() { Text = string.Format("{0}{1}", d, df.DriveType == DriveType.CDRom ? " 光驱" : ""), Tag = d };
                if (df.IsReady && Directory.GetDirectories(d).Count() > 0) tn.Nodes.Add("0");
                tvDrivers.Nodes.Add(tn);
            }
            AddMessage("All", "共有{0}个驱动器", drivers.Length);
        }

        /// <summary>
        /// 显示指定目录所有内容
        /// </summary>
        /// <param name="path"></param>
        public void LoadFolderContent(string path)
        {
            if (!Directory.Exists(path))
            {
                MessageBox.Show(string.Format("路径[{0}]不存在", path));
                return;
            }
            tbPath.Text = path;
            toolTip1.SetToolTip(tbPath, path);
            this.FolderPath = path;
            if (FolderChangeHandler != null) FolderChangeHandler(path);
            lvContents.Items.Clear();
            string[] subfolders = null;
            try
            {
                subfolders = Directory.GetDirectories(path);
            }
            catch (Exception ex)
            {
                AddMessage(ex.Message);
                return;
            }
            foreach (string subf in subfolders)
            {
                lvContents.Items.Add(new ListViewItem() { Text = Path.GetFileName(subf).SubText(0, 9), Tag = subf, ImageKey = "folder", ToolTipText = subf });
            }
            string[] files = Directory.GetFiles(path);
            foreach (string f in files)
            {
                lvContents.Items.Add(new ListViewItem() { Text = Path.GetFileName(f).SubText(0, 9), Tag = f, ImageKey = "file", ToolTipText = f });
            }
            AddMessage("共{0}个文件夹,{1}个文件", subfolders.Length, files.Length);
        }

        // 添加通知消息 ALL | RIGHT | LEFT
        private void AddMessage(string s, params object[] args)
        {
            lblSummary.Text = string.Format(s, args);
        }

        // 菜单点击事件配置
        private void MenuItemClickConfig()
        {
            mil打开ToolStripMenuItem.Click += new EventHandler(cmsLinks_Click);
            mil删除ToolStripMenuItem.Click += new EventHandler(cmsLinks_Click);
            mil刷新ToolStripMenuItem.Click += new EventHandler(cmsLinks_Click);
            mil添加当前目录ToolStripMenuItem.Click += new EventHandler(cmsLinks_Click);
            mil编辑ToolStripMenuItem.Click += new EventHandler(cmsLinks_Click);
        }

        // 链接收藏右键菜单
        private void cmsLinks_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem mi = (ToolStripMenuItem)sender;
            switch (mi.Name)
            {
                case "mil打开ToolStripMenuItem":
                    if (lbLinks.SelectedItem == null) return;
                    this.LoadFolderContent(lbLinks.GetSelectedValue());
                    break;
                case "mil编辑ToolStripMenuItem":
                    if (lbLinks.SelectedItem == null) return;
                    new frmLinkEdit() { Tag = this, MainName = lbLinks.GetSelectedText() }.Show();
                    break;
                case "mil删除ToolStripMenuItem":
                    if (lbLinks.SelectedItem == null) return;
                    if (DialogResult.OK != MessageBox.Show("您确定要删除吗?", "提示", MessageBoxButtons.OKCancel)) return;
                    adh.Delete("tExplorerFavorite", "Name='{0}'".Fmt(lbLinks.GetSelectedText()));
                    this.LoadLinks();
                    break;
                case "mil刷新ToolStripMenuItem":
                    this.LoadLinks();
                    break;
                case "mil添加当前目录ToolStripMenuItem":
                    if (tbPath.TextLength == 0) return;
                    new frmLinkEdit() { Tag = this, HostUri = tbPath.Text }.Show();
                    break;
            }
        }

        // 获取主面板右键菜单 space|file|folder
        private ContextMenuStrip GetMainContextMenu(string type = "space")
        {
            ContextMenuStrip cms = new ContextMenuStrip();
            switch (type)
            {
                case "file": // 文件
                    cms.Items.Add(new ToolStripMenuItem() { Text = "打开(&O)", Name = "打开", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "删除(&D)", Name = "删除", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制(&C)", Name = "复制", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "剪切(&X)", Name = "剪切", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "粘帖(&P)", Name = "粘帖", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "重命名(&R)", Name = "重命名", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制到...(&1)", Name = "复制到", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "剪切到...(&2)", Name = "剪切到", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制文件名(&N)", Name = "复制文件名", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制完整路径(&L)", Name = "复制完整路径", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "用记事本打开(&T)", Name = "用记事本打开", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "压缩(&Z)", Name = "压缩", Tag = "file" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "解压缩(&E)", Name = "解压缩", Tag = "file" });
                    break;
                case "folder": // 文件夹
                    cms.Items.Add(new ToolStripMenuItem() { Text = "打开(&O)", Name = "打开", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "删除(&D)", Name = "删除", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制(&C)", Name = "复制", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "剪切(&X)", Name = "剪切", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "粘帖(&P)", Name = "粘帖", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "重命名(&R)", Name = "重命名", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制到...(&1)", Name = "复制到", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "剪切到...(&2)", Name = "剪切到", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "同步到...(&3)", Name = "同步到", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "查找(&F)", Name = "查找", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制目录名称(&N)", Name = "复制目录名称", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制完整路径(&L)", Name = "复制完整路径", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "资源管理器(&E)", Name = "资源管理器", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "压缩(&Z)", Name = "压缩", Tag = "folder" });
                    cms.Items.Add(new ToolStripMenuItem() { Text="复制所选文件名",Name="复制所选文件名", Tag="folder" });
                    break;
                case "space": // 空白地方
                    cms.Items.Add(new ToolStripMenuItem() { Text = "返回上一级(&P)", Name = "返回上一级", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "排列_列表(&L)", Name = "排列_列表", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "排列_详情(&D)", Name = "排列_详情", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "排列_图标(&I)", Name = "排列_图标", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "命令行(&C)", Name = "命令行", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "刷新(&R)", Name = "刷新", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "查找(&F)", Name = "查找", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "新建_记事本(&T)", Name = "新建_记事本", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "新建_文件夹(&F)", Name = "新建_文件夹", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制完整路径(&L)", Name = "复制完整路径", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "复制目录名称(&N)", Name = "复制目录名称", Tag = "space" });
                    cms.Items.Add(new ToolStripMenuItem() { Text = "资源管理器(&E)", Name = "资源管理器", Tag = "space" });
                    break;
            }
            foreach (ToolStripMenuItem c in cms.Items)
            {
                c.Click += new EventHandler(cmsMainMenuItem_Click);
            }
            return cms;
        }
        protected void cmsMainMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem mi = (ToolStripMenuItem)sender;
            string strMiTag = mi.Tag.ToString(); // space | file | folder
            ListView lv = mi.GetSourceControl<ListView>();
            string tagPath = lv.SelectedItems.Count > 0 ? lv.SelectedItems[0].Tag.ToString() : string.Empty;
            string rootPath = this.FolderPath;
            bool isFile = tagPath.Length > 0 && File.Exists(tagPath);
            switch (mi.Name)
            {
                case "资源管理器":
                    System.Diagnostics.Process.Start(rootPath);
                    break;
                case "打开":
                    if (isFile)
                    {
                        System.Diagnostics.Process.Start(tagPath);
                    }
                    else
                    {
                        this.LoadFolderContent(tagPath);
                    }
                    break;
                case "刷新":
                    this.LoadFolderContent(rootPath);
                    break;
                case "命令行":
                    System.Diagnostics.Process.Start("cmd");
                    break;
                case "删除":
                    if (tagPath.Length == 0) return;
                    if (DialogResult.OK != MessageBox.Show("您确定要删除 [{0}] 吗?".Fmt(Path.GetFileName(tagPath)), "提示", MessageBoxButtons.OKCancel)) return;
                    if (strMiTag == "file") File.Delete(tagPath);
                    if (strMiTag == "folder") Directory.Delete(tagPath, true);
                    this.LoadFolderContent(rootPath);
                    break;
                case "复制":
                case "复制到":
                    frmPathConfirm frmpc = new frmPathConfirm() { Text = "复制到...", FolderPath = this.FolderPath };
                    frmpc.EventHandler = CopyTo;
                    frmpc.Show();
                    break;
                case "返回上一级":
                    this.LoadFolderContent(Path.GetDirectoryName(tbPath.Text));
                    break;
                case "新建_记事本":
                    CreateNewFile();
                    this.LoadFolderContent(tbPath.Text);
                    break;
                case "新建_文件夹":
                    CreateNewFolder();
                    this.LoadFolderContent(tbPath.Text);
                    break;
                case "复制目录名称":
                    Clipboard.SetText(Path.GetFileName(tagPath.Length == 0 ? tbPath.Text : tagPath));
                    break;
                case "复制完整路径":
                    Clipboard.SetText(tagPath.Length == 0 ? tbPath.Text : tagPath);
                    break;
                case "复制文件名":
                    if (isFile) Clipboard.SetText(Path.GetFileName(tagPath));
                    break;
                case "复制所选文件名":
                    if (lvContents.SelectedItems.Count == 0) return;
                    Clipboard.SetText(lvContents.GetSelectedItemsAttrs<string>(a => a.Text).ToString(Environment.NewLine));
                    break;
                case "用记事本打开":
                    if (isFile) System.Diagnostics.Process.Start(Environment.SystemDirectory + "\\notepad", tagPath);
                    break;
            }
        }

        #region 右键菜单私有方法

        // 新建文本文件
        private void CreateNewFile()
        {
            string strNewtxt = tbPath.Text + "\\新建文本文档.txt";
            if (File.Exists(strNewtxt))
            {
                for (int i = 1; i < 99; i++)
                {
                    strNewtxt = string.Format("{0}\\新建文本文档 {1}.txt", tbPath.Text, i);
                    if (!File.Exists(strNewtxt))
                    {
                        File.WriteAllText(strNewtxt, string.Empty);
                        break;
                    }
                }
            }
            else
            {
                File.CreateText(strNewtxt);
            }
        }

        // 新建文件夹
        private void CreateNewFolder()
        {
            string strNewdir = tbPath.Text + "\\新建文件夹";
            if (Directory.Exists(strNewdir))
            {
                for (int i = 1; i < 99; i++)
                {
                    strNewdir = string.Format("{0}\\新建文件夹 {1}", tbPath.Text, i);
                    if (!Directory.Exists(strNewdir))
                    {
                        Directory.CreateDirectory(strNewdir);
                        break;
                    }
                }
            }
            else
            {
                Directory.CreateDirectory(strNewdir);
            }
        }

        // 复制到...
        private void CopyTo(string path)
        {
            foreach (ListViewItem li in lvContents.SelectedItems)
            {
                if (li.ImageKey == "file")
                {
                    File.Copy(li.Tag.ToString(), string.Format("{0}\\{1}", path, Path.GetFileName(li.Tag.ToString())), true);
                }
                if (li.ImageKey == "folder")
                {
                    FileHelper.CopyFolder(li.Tag.ToString(), string.Format("{0}\\{1}", path, Path.GetFileName(li.Tag.ToString())));
                }
            }
            MessageBox.Show("复制完成");
        }
        #endregion

        // 资源管理器列表点击
        private void lv_MouseDown(object sender, MouseEventArgs e)
        {
            ListView lv = (ListView)sender;
            if (e.Button == MouseButtons.Right)
            {
                string stype = "space";
                if (lv.SelectedItems.Count == 1)
                {
                    stype = (lv.SelectedItems[0].ImageKey == "file") ? "file" : "folder";
                    lblSelectedTip.Text = lv.SelectedItems[0].Tag.ToString();
                }
                if (lv.SelectedItems.Count > 1)
                {
                    stype = "folder";
                }
                GetMainContextMenu(stype).Show(lv, e.Location);

            }
        }

        // 资源管理器选择事件
        private void lvContents_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListView lv = (ListView)sender;
            switch (lv.SelectedItems.Count)
            {
                case 0:
                    lblSelectedTip.Text = string.Empty;
                    break;
                case 1:
                    lblSelectedTip.Text = Path.GetFileName(lv.SelectedItems[0].Tag.ToString());
                    toolTip1.SetToolTip(lblSelectedTip, lblSelectedTip.Text);
                    break;
                default:
                    lblSelectedTip.Text = string.Format("已选择 {0} 个项目", lv.SelectedItems.Count);
                    break;
            }
        }

        // 资源管理器列表双击
        private void lv_DoubleClick(object sender, EventArgs e)
        {
            ListView lv = (ListView)sender;
            if (lv.SelectedItems.Count == 0) return;
            if (lv.SelectedItems[0].ImageKey == "file")
            {
                System.Diagnostics.Process.Start(lv.SelectedItems[0].Tag.ToString());
            }
            else
            {
                this.LoadFolderContent(lv.SelectedItems[0].Tag.ToString());
            }
        }

        // 双击快捷连接的时候读取目录的所有子目录和文件
        private void lbLinks_DoubleClick(object sender, EventArgs e)
        {
            if (lbLinks.SelectedIndex == -1) return;
            this.LoadFolderContent(lbLinks.GetSelectedValue());
        }

        // 选中驱动器节点的时候读取目录的所有子目录和文件
        private void tvDrivers_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeView tv = (TreeView)sender;
            if (tv.SelectedNode == null) return;
            if (tv.SelectedNode.Level == 0 && tv.SelectedNode.Text.Contains("光驱")) return;
            this.LoadFolderContent(tv.SelectedNode.Tag.ToString());
        }

        // 驱动器节点展开的时候读取子目录
        private void tvDrivers_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            string[] folders = Directory.GetDirectories(e.Node.Tag.ToString());
            e.Node.Nodes.Clear();
            TreeNode tn;
            foreach (string f in folders)
            {
                tn = new TreeNode() { Text = Path.GetFileName(f), Tag = f };
                try
                {
                    if (Directory.GetDirectories(f).Count() > 0) tn.Nodes.Add("0");
                }
                catch { }

                e.Node.Nodes.Add(tn);
            }
            TreeView tv = (TreeView)sender;
            this.LoadFolderContent(e.Node.Tag.ToString());
        }

        // 驱动器列表关闭的时候清空子目录释放资源
        private void tvDrivers_AfterCollapse(object sender, TreeViewEventArgs e)
        {
            e.Node.Nodes.Clear();
            e.Node.Nodes.Add("0");
        }

        // 打开目录
        private void btnOpenPath_Click(object sender, EventArgs e)
        {
            this.LoadFolderContent(tbPath.Text);
        }

        // 返回上一级
        private void btnBack_Click(object sender, EventArgs e)
        {
            this.LoadFolderContent(Path.GetDirectoryName(tbPath.Text));
        }
    }
}
